package cz.muni.fi.pa165.library.backend;

import cz.muni.fi.pa165.library.api.Available;
import cz.muni.fi.pa165.library.api.Genre;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Implementation of simple CRUD function and fuction for retreaving data from
 * database of DAO entity book.
 *
 * @author Zuzana Foltýnová
 */
@Transactional
@Repository
public class BookDAOImpl implements BookDAO {

    @PersistenceContext(name = "LibraryPU")
    private EntityManager entityManager;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    private void parametersControl(Book book) {
        if (book == null) {
            throw new IllegalArgumentException("Book is null.");
        }
        if (book.getAuthor() == null) {
            throw new IllegalArgumentException("Author has null value.");
        }
        if (book.getAuthor().compareTo("") == 0) {
            throw new IllegalArgumentException("Author field is empty.");
        }
        if (book.getAvailability() == null) {
            throw new IllegalArgumentException("Avaibility has null value.");
        }
        if (book.getGenre() == null) {
            throw new IllegalArgumentException("Genre has null value.");
        }
        if (book.getISBN() == null) {
            throw new IllegalArgumentException("ISBN has null value.");
        }
        if (book.getISBN().compareTo("") == 0) {
            throw new IllegalArgumentException("SBN field is empty.");
        }
        if (book.getPublicationPlace() == null) {
            throw new IllegalArgumentException("Publication place has null value.");
        }
        if (book.getPublicationPlace().compareTo("") == 0) {
            throw new IllegalArgumentException("Publication place field is empty.");
        }
        if (book.getPublicationYear() == null) {
            throw new IllegalArgumentException("Publication year has null value.");
        }
        if (book.getPublicationPlace().compareTo("") == 0) {
            throw new IllegalArgumentException("Publication year field is empty.");
        }
        if (book.getPublisher() == null) {
            throw new IllegalArgumentException("Publisher has null value.");
        }
        if (book.getPublisher().compareTo("") == 0) {
            throw new IllegalArgumentException("Publisher field is empty.");
        }
        if (book.getState() == null) {
            throw new IllegalArgumentException("State has null value.");
        }
        if (book.getTitle() == null) {
            throw new IllegalArgumentException("Title has null value.");
        }
        if (book.getTitle().compareTo("") == 0) {
            throw new IllegalArgumentException("Title field is empty.");
        }
    }

    public Book createBook(Book book) throws IllegalArgumentException {
        if (book == null) {
            throw new IllegalArgumentException("Book is null.");
        }
        if (book.getAvailability() == null) {
            book.setAvailability(Available.AVAILABLE);
        }
        if (book.getAvailability().equals(Available.BORROWED)
                || book.getAvailability().equals(Available.RESERVED)) {
            throw new IllegalArgumentException("Cannot create book which is already "
                    + "borrowed or reserved.");
        }
        parametersControl(book);
        if (book.getId() != null) {
            throw new IllegalArgumentException("Book id is already set");
        }
        entityManager.persist(book);
        return book;
    }

    public List<Book> findAllBooks() {
        List<Book> books = entityManager.createQuery("SELECT e FROM Book e", Book.class).getResultList();
        return books;
    }

    public Book findBookById(Long id) throws IllegalArgumentException {
        if (id == null) {
            throw new IllegalArgumentException("Id searched book is null");
        }
        if (id.intValue() <= 0) {
            throw new IllegalArgumentException("Id searched book is not in correct format");
        }
        Book book = entityManager.find(Book.class, id);
        if (book == null) {
            throw new IllegalArgumentException("Unknown book i: id");
        }
        return book;
    }

    public List<Book> findBookByAuthor(String author) throws IllegalArgumentException {
        if (author == null) {
            throw new IllegalArgumentException("Author has null value.");
        }
        if (author.compareTo("") == 0) {
            throw new IllegalArgumentException("Author field is empty.");
        }
        String query = "SELECT e FROM Book e WHERE e.author LIKE '%" + author + "%'";
        return entityManager.createQuery(query, Book.class).getResultList();
    }

    public List<Book> findBookByTitle(String title) throws IllegalArgumentException {
        if (title == null) {
            throw new IllegalArgumentException("title has null value.");
        }
        if (title.compareTo("") == 0) {
            throw new IllegalArgumentException("title field is empty.");
        }
        String query = "SELECT e FROM Book e WHERE e.title LIKE '%" + title + "%'";
        return entityManager.createQuery(query, Book.class).getResultList();
    }

    public List<Book> findBookByGenre(Genre genre) throws IllegalArgumentException {
        if (genre == null) {
            throw new IllegalArgumentException("Genre has null value.");
        }
        String query = "SELECT e FROM Book e WHERE e.genre = '" + genre + "'";
        return entityManager.createQuery(query, Book.class).getResultList();
    }

    public List<Book> findBookByIsbn(String ISBN) throws IllegalArgumentException {
        if (ISBN == null) {
            throw new IllegalArgumentException("ISBN has null value.");
        }
        if (ISBN.compareTo("") == 0) {
            throw new IllegalArgumentException("ISBN field is empty.");
        }
        String query = "SELECT e FROM Book e WHERE e.ISBN = '" + ISBN + "'";
        return entityManager.createQuery(query, Book.class).getResultList();
    }

    public void updateBook(Book book) throws IllegalArgumentException {
        parametersControl(book);
        Book book1 = findBookById(book.getId());
        if (book1 != null) {
            book1.setAuthor(book.getAuthor());
            book1.setAvailability(book.getAvailability());
            book1.setGenre(book.getGenre());
            book1.setISBN(book.getISBN());
            book1.setPublicationPlace(book.getPublicationPlace());
            book1.setPublicationYear(book.getPublicationYear());
            book1.setPublisher(book.getPublisher());
            book1.setState(book.getState());
            book1.setTitle(book.getTitle());
        } else {
            throw new IllegalArgumentException("Unknown book id:" + book.getId());
        }
        entityManager.merge(book1);
    }

    public void deleteBook(Book book) {
        if (book == null) {
            throw new IllegalArgumentException("Deleted book is Null");
        }

        if (book.getId() == null) {
            throw new IllegalArgumentException("Deleted book id is Null");
        }

        Book newEntity = entityManager.merge(book);
        entityManager.remove(newEntity);
    }

    public List<Book> findAllAvailableBooks() {
        String query = "SELECT e FROM Book e WHERE e.availability = '" + Available.AVAILABLE + "'";
        List<Book> bookList = entityManager.createQuery(query, Book.class).getResultList();
        return bookList;
    }
}
